package com.ryskoo.framework.core.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@SuppressWarnings("unchecked")
@Component
public class RedisUtil {
    private static final Logger logger = LogManager.getLogger("redis");

    @Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private StringRedisTemplate stringRedisTemplate;

    @Autowired
	private void setJsonRedisTemplate(RedisTemplate redisTemplate) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
		this.redisTemplate = redisTemplate;
	}

	/**
	 * 批量删除对应的value
	 * 
	 * @param keys
	 */
	public void remove(final String... keys) {
		for (String key : keys) {
			remove(key);
		}
	}

	/**
	 * 批量删除key
	 * 
	 * @param pattern
	 */
	public void removePattern(final String pattern) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
		Set<Serializable> keys = redisTemplate.keys(pattern);
		if (keys.size() > 0) {
            redisTemplate.delete(keys);
		}
	}

	/**
	 * 删除对应的value
	 * 
	 * @param key
	 */
	public void remove(final String key) {
		if (exists(key)) {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
            redisTemplate.delete(key);
		}
	}

	/**
	 * 判断缓存中是否有对应的value
	 * 
	 * @param key
	 * @return
	 */
	public boolean exists(final String key) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
		return redisTemplate.hasKey(key);
	}

	/**
	 * 读取缓存字符串
	 * 
	 * @param key
	 * @return
	 */
	public String getString(final String key) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
		ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
		return operations.get(key);
	}

	/**
	 * 读取缓存对象
	 *
	 * @param key
	 * @return
	 */
    public Object getObject(final String key) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
		ValueOperations<String, Object> operations = redisTemplate.opsForValue();
		return operations.get(key);
	}

    /**
     * 读取缓存对象
     *
     * @param key
     * @return
     */
    public Object getObject(final String key, Class clazz) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        ValueOperations<String, Object> operations = redisTemplate.opsForValue();
        return operations.get(key);
    }

	/**
	 * 读取缓存Session
	 *
	 * @param key
	 * @return
	 */
	public Object getSession(final String key) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer(getClass().getClassLoader()));
		ValueOperations<String, Object> operations = redisTemplate.opsForValue();
		return operations.get(key);
	}

	/**
	 * 写入缓存字符串
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean setString(final String key, String value) {
		boolean result = false;
		try {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new StringRedisSerializer());
			ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
			operations.set(key, value);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 写入缓存对象
	 *
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean setObject(final String key, Object value) {
		boolean result = false;
		try {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			result = true;
		} catch (Exception e) {
			logger.error("redis set object error", e);
		}
		return result;
	}

	/**
	 * 写入缓存字符串，带过期时长
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean setExpireString(final String key, String value, Long expireTime) {
		boolean result = false;
		try {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new StringRedisSerializer());
			ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
			operations.set(key, value);
			stringRedisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 写入缓存对象，带过期时长
	 *
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean setExpireObject(final String key, Object value, Long expireTime, TimeUnit unit) {
		boolean result = false;
		try {
			redisTemplate.setKeySerializer(new StringRedisSerializer());
			redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			redisTemplate.expire(key, expireTime, unit);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 写入缓存对象，带过期时长
	 *
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean setExpireObject(final String key, Object value, Long expireTime) {
		return setExpireObject(key, value, expireTime, TimeUnit.SECONDS);
	}

	/**
	 * 写入缓存对象，带过期时长
	 *
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean setExpireSession(final String key, Object value,Long expireTime) {
		boolean result = false;
		try {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer(getClass().getClassLoader()));
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			if (null != expireTime) {
                redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
			}
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public boolean setExpireTime(final String key, Long expireTime) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer(getClass().getClassLoader()));
	    return redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
	}

	public boolean setExpireTime(final String key, Long expireTime, TimeUnit timeUnit) {
		try {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
            redisTemplate.expire(key, expireTime, timeUnit);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public boolean hmset(String key, Map<String, String> value) {
		boolean result = false;
		try {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
            redisTemplate.opsForHash().putAll(key, value);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public Map<String, String> hmget(String key) {
		Map<String, String> result = null;
		try {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
			result = redisTemplate.opsForHash().entries(key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
}
